package com.pyl.admin.system.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.github.pagehelper.PageInfo;
import com.pyl.admin.core.constant.AdminConst;
import com.pyl.admin.core.enums.ResultEnum;
import com.pyl.admin.core.enums.StatusEnum;
import com.pyl.admin.core.enums.UserIsRoleEnum;
import com.pyl.admin.core.excel.ExcelUtil;
import com.pyl.admin.core.exception.ResultException;
import com.pyl.admin.core.shiro.ShiroUtil;
import com.pyl.admin.system.entity.SysRole;
import com.pyl.admin.system.entity.SysUser;
import com.pyl.admin.system.entity.SysUserRole;
import com.pyl.admin.system.service.SysRoleService;
import com.pyl.admin.system.service.SysUserRoleService;
import com.pyl.admin.system.service.SysUserService;
import com.pyl.admin.system.validator.UserForm;
import com.pyl.core.config.properties.ProjectProperties;
import com.pyl.core.utils.ResultVoUtil;
import com.pyl.core.utils.SpringContextUtil;
import com.pyl.core.vo.ResultVo;

import cn.hutool.core.collection.CollectionUtil;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author 灵魂贰婶
 * @since 2019-06-28
 */
@Controller
@RequestMapping("/system/user")
public class SysUserController {

	@Autowired
	private SysUserService sysUserService;

	@Autowired
	private SysRoleService sysRoleService;

	@Autowired
	private SysUserRoleService sysUserRoleService;

	/**
	 * 列表页面
	 */
	@GetMapping("/index")
	@RequiresPermissions("/system/user/index")
	public String index(Model model, 
			@RequestParam(required = false, defaultValue = "1") Integer status,
			@RequestParam(required = false) String query, @RequestParam(required = false) Long deptId) {
		// 获取用户列表
		PageInfo<SysUser> page = sysUserService.selectUserListPage( status, query, deptId);
		// 封装数据
		model.addAttribute("list", page.getList());
		model.addAttribute("page", page);
		return "/system/user/index";
	}

	/**
	 * 跳转到添加页面
	 */
	@GetMapping("/add")
	@RequiresPermissions("/system/user/add")
	public String toAdd() {
		return "/system/user/add";
	}

	/**
	 * 跳转到编辑页面
	 */
	@GetMapping("/edit/{id}")
	@RequiresPermissions("/system/user/edit")
	public String toEdit(@PathVariable("id") Long id, Model model) {
		SysUser sysUser = sysUserService.selectById(id);
		model.addAttribute("user", sysUser);
		return "/system/user/add";
	}

	/**
	 * 保存添加/修改的数据
	 *
	 * @param userForm 表单验证对象
	 */
	@PostMapping("/save")
	@RequiresPermissions({ "/system/user/add", "/system/user/edit" })
	@ResponseBody
	public ResultVo<?> save(@Validated UserForm userForm) {
		sysUserService.saveOrUpdate(userForm);
		return ResultVoUtil.SAVE_SUCCESS;
	}

	/**
	 * 跳转到详细页面
	 */
	@GetMapping("/detail/{id}")
	@RequiresPermissions("/system/user/detail")
	public String toDetail(@PathVariable("id") Long id, Model model) {
		SysUser sysUser = sysUserService.selectById(id);
		model.addAttribute("user", sysUser);
		return "/system/user/detail";
	}

	/**
	 * 跳转到修改密码页面
	 */
	@GetMapping("/pwd")
	@RequiresPermissions("/system/user/pwd")
	public String toEditPassword(Model model, @RequestParam(value = "ids", required = false) List<Long> idList) {
		model.addAttribute("idList", idList);
		return "/system/user/pwd";
	}

	/**
	 * 修改密码
	 */
	@PostMapping("/pwd")
	@RequiresPermissions("/system/user/pwd")
	@ResponseBody
	public ResultVo<?> editPassword(@RequestParam(value = "password") String password,
			@RequestParam(value = "confirm") String confirm, @RequestParam(value = "ids") List<Long> idList) {

		// 判断密码是否为空
		if (password.isEmpty() || "".equals(password.trim())) {
			throw new ResultException(ResultEnum.USER_PWD_NULL);
		}

		// 8-16位数字或字母
		String pattern = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$";
		if (!Pattern.matches(pattern, password)) {
			throw new ResultException(500, "密码不符合要求必须8-16位之间数字字母组合");
		}

		// 判断两次密码是否一致
		if (!password.equals(confirm)) {
			throw new ResultException(ResultEnum.USER_INEQUALITY);
		}

		// 不允许操作超级管理员数据
		if (idList.contains(AdminConst.ADMIN_ID) && !ShiroUtil.getSubject().getId().equals(AdminConst.ADMIN_ID)) {
			throw new ResultException(ResultEnum.NO_ADMIN_AUTH);
		}

		// 修改密码，对密码进行加密
		List<SysUser> userList = sysUserService.selectBatchIds(idList);

		for (int i = 0; i < userList.size(); i++) {
			SysUser sysUser = userList.get(i);
			String salt = ShiroUtil.getRandomSalt();
			String encrypt = ShiroUtil.encrypt(password, salt);
			sysUser.setPassword(encrypt);
			sysUser.setSalt(salt);
			sysUser.setUpdateDate(new Date());
			sysUserService.updateById(sysUser);
		}
		return ResultVoUtil.success("修改成功");
	}

	/**
	 * 跳转到角色分配页面
	 */
	@GetMapping("/role")
	@RequiresPermissions("/system/user/role")
	public String toRole(@RequestParam(value = "ids") Long id, Model model) {
		// 获取指定用户角色列表
		SysUser sysUser = sysUserService.selectUserAndRoleById(id);
		List<SysRole> authRoles = sysUser.getRoles();
		// 获取全部菜单列表
		List<SysRole> sysRoles = sysRoleService
				.selectList(new EntityWrapper<SysRole>().eq("status", Integer.valueOf(StatusEnum.OK.getCode())));
		// 融合两项数据
		for (int i = 0; i < sysRoles.size(); i++) {
			for (int j = 0; j < authRoles.size(); j++) {
				if (authRoles.get(j).getId().equals(sysRoles.get(i).getId())) {
					sysRoles.get(i).setRemark("auth:true");
				}
			}
		}

		model.addAttribute("id", id);
		model.addAttribute("list", sysRoles);
		return "/system/user/role";
	}

	/**
	 * 保存角色分配信息
	 */
	@PostMapping("/role")
	@RequiresPermissions("/system/user/role")
	@ResponseBody
	public ResultVo<?> auth(@RequestParam(value = "id", required = true) Long id,
			@RequestParam(value = "roleId", required = false) List<Long> roleIds) {
		// 不允许操作超级管理员数据
		if (id.equals(AdminConst.ADMIN_ID) && !ShiroUtil.getSubject().getId().equals(AdminConst.ADMIN_ID)) {
			throw new ResultException(ResultEnum.NO_ADMIN_AUTH);
		}
		// 将查询的数据关联起来
		SysUser sysUser = sysUserService.selectById(id);
		List<SysRole> roleList = null;
		// 重置用户角色
		sysUserRoleService.delete(new EntityWrapper<SysUserRole>().eq("user_id", sysUser.getId()));
		if (CollectionUtil.isNotEmpty(roleIds)) {
			roleList = sysRoleService.selectBatchIds(roleIds);
			List<SysUserRole> list = new ArrayList<>();
			for (int i = 0; i < roleList.size(); i++) {
				SysUserRole sysUserRole = new SysUserRole();
				sysUserRole.setUserId(sysUser.getId());
				sysUserRole.setRoleId(roleList.get(i).getId());
				list.add(sysUserRole);
			}
			sysUserRoleService.insertBatch(list);
			sysUser.setIsRole(Integer.valueOf(UserIsRoleEnum.YES.getCode()));
			sysUser.setUpdateDate(new Date());
			sysUserService.updateById(sysUser);
		}else {
			sysUser.setIsRole(Integer.valueOf(UserIsRoleEnum.NO.getCode()));
			sysUser.setUpdateDate(new Date());
			sysUserService.updateById(sysUser);
		}
		return ResultVoUtil.SAVE_SUCCESS;
	}

	/**
	 * 获取用户头像
	 */
	@GetMapping("/picture")
	public void picture(String p, HttpServletResponse response) throws IOException {
		String defaultPath = "/images/user-picture.png";
		if (!(StringUtils.isEmpty(p) || p.equals(defaultPath))) {
			ProjectProperties properties = SpringContextUtil.getBean(ProjectProperties.class);
			String fuPath = properties.getFileUploadPath();
			String spPath = properties.getStaticPathPattern().replace("*", "");
			File file = new File(fuPath + p.replace(spPath, ""));
			if (file.exists()) {
				FileCopyUtils.copy(new FileInputStream(file), response.getOutputStream());
				return;
			}
		}
		Resource resource = new ClassPathResource("static" + defaultPath);
		FileCopyUtils.copy(resource.getInputStream(), response.getOutputStream());
	}

	/**
	 * 导出用户数据
	 */
	@GetMapping("/export")
	@ResponseBody
	public void exportExcel() {
		ExcelUtil.exportExcel(SysUser.class, sysUserService
				.selectList(new EntityWrapper<SysUser>().ne("status", Integer.valueOf(StatusEnum.DELETE.getCode()))));
	}

	/**
	 * 设置一条或者多条数据的状态
	 */
	@RequestMapping("/status/{param}")
	@RequiresPermissions("/system/user/status")
	@ResponseBody
	public ResultVo<?> delete(@PathVariable("param") String param,
			@RequestParam(value = "ids", required = false) List<Long> idList) {
		// 不能修改超级管理员状态
		if (idList.contains(AdminConst.ADMIN_ID)) {
			throw new ResultException(ResultEnum.NO_ADMIN_STATUS);
		}
		try {
			// 获取状态StatusEnum对象
			StatusEnum statusEnum = StatusEnum.valueOf(param.toUpperCase());
			// 更新状态
			boolean result = sysUserService.updateStatus(statusEnum, idList);
			return result ? ResultVoUtil.success(statusEnum.getMessage() + "成功")
					: ResultVoUtil.error(statusEnum.getMessage() + "失败，请重新操作");
		} catch (IllegalArgumentException e) {
			throw new ResultException(ResultEnum.STATUS_ERROR);
		}
	}

}
